package com.wyh.domain.vo.groupOne.utils;

import com.wyh.domain.vo.groupOne.threemeterTree.*;


import java.util.*;

public class MasterDataDepartmentTree {

//    只生成含有组织的树
    public static List<MasterDataTreeNode> buildUserDepartmentTree(int userId, int userOrgId, List<MasterDataOrganizationVO> aList){
        Map<Integer, MasterDataTreeNode> aNodeMap = new HashMap<>();
        int unique_id = 0;

        // Create MasterDataTreeNode for each MasterDataOrganizationVO and map it
        for (MasterDataOrganizationVO a : aList) {
            unique_id++;
            MasterDataTreeNode node = new MasterDataTreeNode(unique_id, a.getId(), a.getName(), "organization",a.getState());
            aNodeMap.put(a.getId(), node);
        }

        // Link MasterDataOrganizationVO nodes to their parents
        for (MasterDataOrganizationVO a : aList) {
            if (a.getSuperiorId() != 0) {
                MasterDataTreeNode node = aNodeMap.get(a.getId());
                MasterDataTreeNode parentNode = aNodeMap.get(a.getSuperiorId());
                parentNode.getChildren().add(node);
            }
        }
        // Find the user's organization node
        MasterDataTreeNode userOrgNode = aNodeMap.get(userOrgId);
        if (userOrgNode == null) {
            return Collections.emptyList(); // OrganizationPO not found
        }

        // Find the root node of the user's organization
        MasterDataTreeNode rootNode = findRootNode(userOrgNode, aNodeMap);

        // Prune the tree to include only the relevant nodes for the user
        MasterDataTreeNode prunedTree = pruneTree(rootNode, userOrgNode);

        // Return the pruned tree starting from the root node
        return Collections.singletonList(prunedTree);
    }




    //    只生成含有组织与下属项目的树
    public static List<MasterDataTreeNode> buildUserDepartmentTree(int userId, int userOrgId, List<MasterDataOrganizationVO> aList, List<MasterDataProjectVO> bList){
        Map<Integer, MasterDataTreeNode> aNodeMap = new HashMap<>();
        Map<Integer, MasterDataTreeNode> bNodeMap = new HashMap<>();
        int unique_id = 0;

        // Create MasterDataTreeNode for each MasterDataOrganizationVO and map it
        for (MasterDataOrganizationVO a : aList) {
            unique_id++;
            MasterDataTreeNode node = new MasterDataTreeNode(unique_id, a.getId(), a.getName(), "organization",a.getState());
            aNodeMap.put(a.getId(), node);
        }

        // Link MasterDataOrganizationVO nodes to their parents
        for (MasterDataOrganizationVO a : aList) {
            if (a.getSuperiorId() != 0) {
                MasterDataTreeNode node = aNodeMap.get(a.getId());
                MasterDataTreeNode parentNode = aNodeMap.get(a.getSuperiorId());
                parentNode.getChildren().add(node);
            }
        }

        // Create MasterDataTreeNode for each MasterDataProjectVO_1 and map it
        for (MasterDataProjectVO b : bList) {
            MasterDataTreeNode node;
            if (b.getType() == 1) {
                unique_id++;
                node = new MasterDataTreeNode(unique_id, b.getId(), b.getName(), "houses",b.getState());
            } else {
                unique_id++;
                node = new MasterDataTreeNode(unique_id, b.getId(), b.getName(), "gardenArea",b.getState());
            }

            bNodeMap.put(b.getId(), node);
            if ("Y".equals(b.getIsConnected())) {
                MasterDataTreeNode parentNode = aNodeMap.get(b.getSuperiorId());
                parentNode.getChildren().add(node);
            }
        }

        // Link MasterDataProjectVO_1 nodes to their parents in MasterDataProjectVO_1
        for (MasterDataProjectVO b : bList) {
            if ("N".equals(b.getIsConnected())) {
                MasterDataTreeNode node = bNodeMap.get(b.getId());
                MasterDataTreeNode parentNode = bNodeMap.get(b.getSuperiorId());
                parentNode.getChildren().add(node);
            }
        }

        // Find the user's organization node
        MasterDataTreeNode userOrgNode = aNodeMap.get(userOrgId);
        if (userOrgNode == null) {
            return Collections.emptyList(); // OrganizationPO not found
        }

        // Find the root node of the user's organization
        MasterDataTreeNode rootNode = findRootNode(userOrgNode, aNodeMap);

        // Prune the tree to include only the relevant nodes for the user
        MasterDataTreeNode prunedTree = pruneTree(rootNode, userOrgNode);

        // Return the pruned tree starting from the root node
        return Collections.singletonList(prunedTree);
    }







//    完整的树
//    List<MasterDataTreeNode>
    public static List<MasterDataTreeNode> buildUserDepartmentTree(int userId, int userOrgId, List<MasterDataOrganizationVO> aList, List<MasterDataProjectVO> bList,
                                                                   List<MasterDataBuildingUnitsVO> cList, List<MasterDataLayerVO_1> dList,
                                                                   List<MasterDataRoomVO> eList) {
        Map<Integer, MasterDataTreeNode> aNodeMap = new HashMap<>();
        Map<Integer, MasterDataTreeNode> bNodeMap = new HashMap<>();
        Map<Integer, MasterDataTreeNode> cNodeMap = new HashMap<>();
        Map<Integer, MasterDataTreeNode> dNodeMap = new HashMap<>();
        Map<Integer, MasterDataTreeNode> eNodeMap = new HashMap<>();
        int unique_id = 0;

        // Create MasterDataTreeNode for each MasterDataOrganizationVO and map it
        for (MasterDataOrganizationVO a : aList) {
            unique_id++;
            MasterDataTreeNode node = new MasterDataTreeNode(unique_id, a.getId(), a.getName(), "organization",a.getState());
            aNodeMap.put(a.getId(), node);
        }

        // Link MasterDataOrganizationVO nodes to their parents
        for (MasterDataOrganizationVO a : aList) {
            if (a.getSuperiorId() != 0) {
                MasterDataTreeNode node = aNodeMap.get(a.getId());
                MasterDataTreeNode parentNode = aNodeMap.get(a.getSuperiorId());
                if (parentNode!=null){
//                    设置上一级的id，方便回溯遍历
                    node.setParentUniqueId(parentNode.getUnique_id());
                    parentNode.getChildren().add(node);
                }
            }
        }

        // Create MasterDataTreeNode for each MasterDataProjectVO_1 and map it
        for (MasterDataProjectVO b : bList) {

            MasterDataTreeNode node;
            if (b.getType() == 1) {
                unique_id++;
                node = new MasterDataTreeNode(unique_id, b.getId(), b.getName(), "houses",b.getState());
            } else {
                unique_id++;
                node = new MasterDataTreeNode(unique_id, b.getId(), b.getName(), "gardenArea",b.getState());
            }

            bNodeMap.put(b.getId(), node);
            if ("Y".equals(b.getIsConnected())) {
                MasterDataTreeNode parentNode = aNodeMap.get(b.getSuperiorId());
                if (parentNode!=null){
                    node.setParentUniqueId(parentNode.getUnique_id());
                    parentNode.getChildren().add(node);
                }
            }
        }

        // Link MasterDataProjectVO_1 nodes to their parents in MasterDataProjectVO_1
        for (MasterDataProjectVO b : bList) {
            if ("N".equals(b.getIsConnected())) {
                MasterDataTreeNode node = bNodeMap.get(b.getId());
                MasterDataTreeNode parentNode = bNodeMap.get(b.getSuperiorId());
                if (parentNode!=null){
                    node.setParentUniqueId(parentNode.getUnique_id());
                    parentNode.getChildren().add(node);
                }
            }
        }

        // Create MasterDataTreeNode for each MasterDataBuildingUnitsVO and map it
        for (MasterDataBuildingUnitsVO c : cList) {
            MasterDataTreeNode node;
            if (c.getType() == 0) {
                // Cluster
                unique_id++;
                node = new MasterDataTreeNode(unique_id, c.getId(), c.getName(), "cluster", c.getState());
            } else if (c.getType() == 1) {
                // Building
                unique_id++;
                node = new MasterDataTreeNode(unique_id, c.getId(), c.getName(), "building",c.getState());
            } else {
                // Unit
                unique_id++;
                node = new MasterDataTreeNode(unique_id, c.getId(), c.getName(), "unit",c.getState());
            }
            cNodeMap.put(c.getId(), node);
            if ("Y".equals(c.getIsConnected())) {
                MasterDataTreeNode parentNode = bNodeMap.get(c.getParentId());
                if (parentNode!=null){
                    node.setParentUniqueId(parentNode.getUnique_id());
                    parentNode.getChildren().add(node);
                }
            }
        }

        // Link MasterDataBuildingUnitsVO nodes to their parents in MasterDataBuildingUnitsVO
        for (MasterDataBuildingUnitsVO c : cList) {
            if ("N".equals(c.getIsConnected())) {
                MasterDataTreeNode node = cNodeMap.get(c.getId());
                MasterDataTreeNode parentNode = cNodeMap.get(c.getParentId());
                if (parentNode!=null){
                    node.setParentUniqueId(parentNode.getUnique_id());
                    parentNode.getChildren().add(node);
                }
            }
        }

        // Create MasterDataTreeNode for each MasterDataLayerVO_1 and map it
        for (MasterDataLayerVO_1 d : dList) {
            unique_id++;
            MasterDataTreeNode node = new MasterDataTreeNode(unique_id, d.getId(), d.getName(), "layer",d.getState());
            dNodeMap.put(d.getId(), node);
            MasterDataTreeNode parentNode = cNodeMap.get(d.getParentId());
            if (parentNode!=null){
                node.setParentUniqueId(parentNode.getUnique_id());
                parentNode.getChildren().add(node);
            }
        }

        // Create MasterDataTreeNode for each MasterDataRoomVO and map it
        for (MasterDataRoomVO e : eList) {
            if (e.getState() == 1 || e.getState() == 2 || e.getState()==0) { // Check if the state is 1 or 2
                MasterDataTreeNode node;
                if (e.getType() == 0) {
                    unique_id++;
                    node = new MasterDataTreeNode(unique_id, e.getId(), e.getName(), "room",1);
                } else {
                    unique_id++;
                    node = new MasterDataTreeNode(unique_id, e.getId(), e.getName(), "parkingSpot",1);
                }
                eNodeMap.put(e.getId(), node);
                MasterDataTreeNode parentNode = dNodeMap.get(e.getBuildingId());
                if (parentNode!=null){
                    node.setParentUniqueId(parentNode.getUnique_id());
                    parentNode.getChildren().add(node);
                }
            }
        }

        // Find the user's organization node
        MasterDataTreeNode userOrgNode = aNodeMap.get(userOrgId);
        if (userOrgNode == null) {
            return Collections.emptyList(); // OrganizationPO not found
        }

        // Find the root node of the user's organization
        MasterDataTreeNode rootNode = findRootNode(userOrgNode, aNodeMap);

        // Prune the tree to include only the relevant nodes for the user
        MasterDataTreeNode prunedTree = pruneTree(rootNode, userOrgNode);

        // Return the pruned tree starting from the root node
        return Collections.singletonList(prunedTree);
//        return prunedTree;
    }

    private static MasterDataTreeNode findRootNode(MasterDataTreeNode node, Map<Integer, MasterDataTreeNode> nodeMap) {
        while (node.getParentUniqueId() != -1) {
            node = nodeMap.get(node.getParentUniqueId());
        }
        return node;
    }

    private static MasterDataTreeNode pruneTree(MasterDataTreeNode rootNode, MasterDataTreeNode userOrgNode) {
        if (rootNode == userOrgNode) {
            return rootNode;
        }

        MasterDataTreeNode prunedNode = new MasterDataTreeNode(rootNode.getUnique_id(), rootNode.getId(), rootNode.getName(), rootNode.getType(),rootNode.getState());
        for (MasterDataTreeNode child : rootNode.getChildren()) {
            MasterDataTreeNode prunedChild = pruneTree(child, userOrgNode);
            if (prunedChild != null) {
                prunedNode.getChildren().add(prunedChild);
            }
        }
        return prunedNode.getChildren().isEmpty() ? null : prunedNode;
    }

    public static MasterDataTreeNode removeDisabledNodes(MasterDataTreeNode node) {
        if (node == null) {
            return null;
        }
        if (node.getState()==0&&!("roomparkingSpot").contains(node.getType())) {
            return null; // 如果当前节点已禁用，直接返回 null
        }
        List<MasterDataTreeNode> prunedChildren = new ArrayList<>();
        for (MasterDataTreeNode child : node.getChildren()) {
            MasterDataTreeNode prunedChild = removeDisabledNodes(child);
            if (prunedChild != null) {
                prunedChildren.add(prunedChild);
            }
        }
        node.setChildren(prunedChildren);
        return node;
    }

    public static String getPathFromNode(MasterDataTreeNode node, Map<Integer, MasterDataTreeNode> nodeMap) {
        List<String> path = new ArrayList<>();
        while (node != null) {
            path.add(0, node.getName());
            if (node.getParentUniqueId() == -1) {
                break;
            }
            node = nodeMap.get(node.getParentUniqueId());
        }
        return String.join("/", path);
    }



    // 根据节点id与节点type查找并返回其子树
    public static MasterDataTreeNode getSubTree(int housesId, String type, List<MasterDataTreeNode> tree) {
        MasterDataTreeNode nodeResult = findNodeByIdAndType(tree.get(0), housesId, type);
            return nodeResult;
//        for (MasterDataTreeNode node : tree) {
//            MasterDataTreeNode result = findNodeByIdAndType(node, housesId, type);
//            if (result != null) {
//                return result;
//            }
//        }
//        return null;
    }

    // 递归查找匹配的节点
    private static MasterDataTreeNode findNodeByIdAndType(MasterDataTreeNode node, int id, String type){
        if (node.getId()==id&&node.getType().equals(type)){
            return node;
        }
        for (MasterDataTreeNode masterDataTreeNode :node.getChildren()
             ) {
            MasterDataTreeNode node2 = findNodeByIdAndType(masterDataTreeNode, id, type);
            if (node2!=null){
                return node2;
            }
        }
        return null;
    }
}

